package cn.ydw.community.service.impl;

import cn.ydw.community.dao.elasticsearch.DiscussPostElasticSearch;
import cn.ydw.community.entity.DiscussPost;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.ScoreSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class ElasticService {

    @Autowired
    private DiscussPostElasticSearch postElasticSearch;

    @Autowired
    private RestHighLevelClient client;

    /**
     * 保存一个 discussPost 对象到es中
     *
     * @param discussPost
     */
    public void save(DiscussPost discussPost) {
        postElasticSearch.save(discussPost);
    }

    public void deletePostById(Integer id) {
        postElasticSearch.deleteById(Long.valueOf(id));
    }

    /**
     * 搜索
     */
    public List<DiscussPost> search(String keyword, int offset, int limit, Model model) throws IOException {
        String preTag = "<font color='red'>";
        String postTag = "</font>";
        SearchRequest searchRequest = new SearchRequest("discusspost");
        // 搜索构建
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(
                QueryBuilders.multiMatchQuery(keyword, "title", "content").analyzer("ik_smart"))
                .sort(new ScoreSortBuilder().order(SortOrder.DESC))
                .from(offset)
                .size(limit);
        // 高亮构建
        HighlightBuilder highlightBuilder = new HighlightBuilder().preTags(preTag)
                .postTags(postTag)
                .field("title")
                .field("content");
        searchSourceBuilder.highlighter(highlightBuilder);
        searchRequest.source(searchSourceBuilder);
        //获取搜索相应结果
        SearchResponse searchResponse;
        searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchResponse.getHits();

        TotalHits totalHits = hits.getTotalHits();
        // 命中总数
        long numHits = totalHits.value;
        // 最大匹配精度
//        float maxScore = hits.getMaxScore();
        SearchHit[] searchHits = hits.getHits();
        model.addAttribute("totalRows", numHits);

        List<DiscussPost> discussPosts = new ArrayList<>();
        for (SearchHit hit : searchHits) {
            DiscussPost post = JSONObject.parseObject(hit.getSourceAsString(), DiscussPost.class);
//            System.out.println(post);
            Map<String, HighlightField> fields = hit.getHighlightFields();
            // 得到高亮字段
            HighlightField title = fields.get("title");
            HighlightField content = fields.get("content");
            if (title != null) {
                post.setTitle("");
                for (Text text : title.getFragments()) {
                    post.setTitle(post.getTitle() + text.string());
                }
            }
            if (content != null) {
                post.setContent("");
                for (Text text : content.fragments()) {
                    post.setContent(post.getContent() + text.string());
                }
            }
            log.info(post.toString());
            discussPosts.add(post);
        }
        return discussPosts;
    }
}
